package br.poli.ecomp.ads.sablecceditor.editors;

import java.util.ArrayList;
import java.util.HashMap;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextEditor;

import br.poli.ecomp.ads.sablecceditor.SableCCPlugin;
import br.poli.ecomp.ads.sablecceditor.editors.color.SableCCColorManager;
import br.poli.ecomp.ads.sablecceditor.editors.configuration.SableCCSourceViewerConfiguration;
import br.poli.ecomp.ads.sablecceditor.editors.scanner.SableCCScanner;
import br.poli.ecomp.ads.sablecceditor.preferences.PreferenceConstants;

public class SableCCEditor extends TextEditor {

	private SableCCColorManager colorManager;
	private ProjectionSupport projectionSupport;
	private Annotation[] oldAnnotations;
	private ProjectionAnnotationModel annotationModel;
	private static SableCCScanner sableCCScanner;

	public SableCCEditor() {
		super();
		setDocumentProvider(new SableCCDocumentProvider());
		this.sableCCScanner = new SableCCScanner(this.colorManager);
		SableCCPlugin.getDefault().getPreferenceStore()
				.addPropertyChangeListener(new IPropertyChangeListener() {

					@Override
					public void propertyChange(PropertyChangeEvent event) {
						System.out.println(event.getProperty());
						if (event.getProperty().equals(
								PreferenceConstants.COLOR_COMMENT)
								|| event.getProperty().equals(
										PreferenceConstants.COLOR_DEFAULT)
								|| event.getProperty().equals(
										PreferenceConstants.COLOR_KEYWORD)
								|| event.getProperty().equals(
										PreferenceConstants.COLOR_STRING)
								|| event.getProperty().equals(
										PreferenceConstants.COLOR_OPERATION)) {

							try {
								String content = getDocumentProvider()
										.getDocument(getEditorInput()).get();
								init(getEditorSite(), getEditorInput());
								getDocumentProvider().getDocument(
										getEditorInput()).set(content);
							} catch (PartInitException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

						}
					}
				});
	}

	public static SableCCScanner getSableCCScanner() {
		return sableCCScanner;
	}

	protected void adjustHighlightRange(int offset, int length) {
		ISourceViewer viewer = getSourceViewer();
		if (viewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
			extension.exposeModelRange(new Region(offset, length));
		}
	}
	
	@Override
	public void doSave(IProgressMonitor progressMonitor) {
		// TODO Auto-generated method stub
		super.doSave(progressMonitor);
	}

	public void dispose() {
		colorManager.dispose();
		super.dispose();
	}

	@Override
	protected void initializeEditor() {
		super.initializeEditor();
		colorManager = new SableCCColorManager();
		setSourceViewerConfiguration(new SableCCSourceViewerConfiguration(
				colorManager, this));
	}

	public void createPartControl(Composite parent) {
		super.createPartControl(parent);
		ProjectionViewer viewer = (ProjectionViewer) getSourceViewer();
		projectionSupport = new ProjectionSupport(viewer,
				getAnnotationAccess(), getSharedColors());
		projectionSupport.install();
		// turn projection mode on
		viewer.doOperation(ProjectionViewer.TOGGLE);
		annotationModel = viewer.getProjectionAnnotationModel();

	}

	public ProjectionAnnotationModel getAnnotationModel() {
		return annotationModel;
	}

	@SuppressWarnings("all")
	public void updateFoldingStructure(ArrayList positions) {
		Annotation[] annotations = new Annotation[positions.size()];
		// this will hold the new annotations along
		// with their corresponding positions
		HashMap newAnnotations = new HashMap();
		for (int i = 0; i < positions.size(); i++) {
			ProjectionAnnotation annotation = new ProjectionAnnotation();
			newAnnotations.put(annotation, positions.get(i));
			annotations[i] = annotation;
		}
		annotationModel.modifyAnnotations(oldAnnotations, newAnnotations, null);
		oldAnnotations = annotations;
	}

	protected ISourceViewer createSourceViewer(Composite parent,
			IVerticalRuler ruler, int styles) {
		ISourceViewer viewer = new ProjectionViewer(parent, ruler,
				getOverviewRuler(), isOverviewRulerVisible(), styles);
		getSourceViewerDecorationSupport(viewer);

		return viewer;
	}

}
